package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import javax.net.ssl.SSLSocket;

public class ClientHandler extends Thread {
	private BufferedReader in;
	private RecordDatabas data;
	private BufferedWriter out;

	public enum ActionType {
		LIST, READ, UPDATE, WRITE, DELETE, ADD, HELP, WHOAMI
	}

	private User loggedInUser;

	public ClientHandler(SSLSocket socket, RecordDatabas data, long ssn,
			Group group, int division) throws IOException {
		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		OutputStream outputstream = socket.getOutputStream();
		OutputStreamWriter outputstreamwriter = new OutputStreamWriter(
				outputstream);
		out = new BufferedWriter(outputstreamwriter);

		this.loggedInUser = new User(ssn, division, group);
		this.data = data;
		this.start();
	}

	public void run() {
		try {
			System.out.println("running");
			System.out.println("Authenticated");
			while (true) {
				String input = in.readLine();
				String[] param = input.split(";");
				UserInputLogger.log(String.format("FROM %010d:",
						loggedInUser.getSsn())
						+ " \"" + input + "\"");
				ActionType type;

				try {
					type = ActionType.valueOf(ActionType.class, param[0]);
				} catch (IllegalArgumentException e) {
					terminate();
					return;
				}
				switch (type) {
				case WHOAMI:
					sendToClient(String.format("%010d", loggedInUser.getSsn())
							+ " " + loggedInUser.getDivision());
					break;
				case HELP:
					sendToClient("ADD;SSN;DIVISION;NURSE;RECORD\nLIST\nREAD;SSN;"
							+ "TIMESTAMP\nDELETE;SSN;TIMESTAMP\nWRITE;SSN;TIMESTAMP;DIVISION;NURSE;RECORD\nWHOAMI");
					break;
				case ADD:
					if (param.length < 5) {
						terminate();
						return;
					} else {
						long ssnOfSubject = parseLong(param[1]);
						int division = Integer.parseInt(param[2]);
						long doctor = loggedInUser.getSsn();
						long nurse = parseLong(param[3]);
						String record = param[4];
						Record r = new Record(ssnOfSubject, doctor, division,
								nurse, record);

						if (data.addRecord(loggedInUser, r))
							sendToClient("new record added");
						else
							sendToClient("NAJ!");
					}
					break;
				case LIST:
					System.out.println("returning the list");
					sendToClient(data.listRecords(loggedInUser));
					break;
				case READ:
					System.out.println("returning a specific record");
					Record record = data.readRecord(loggedInUser,
							parseLong(param[1]), parseLong(param[2]));
					sendToClient(record == null ? "Finns inte" : record
							.toString());
					break;
				case DELETE:
					System.out.println("Deleting stuff");
					if (data.deleteRecord(loggedInUser, parseLong(param[1]),
							parseLong(param[2])))
						sendToClient("delete treu");
					else
						sendToClient("delete false");
					break;
				case WRITE:
					if (param.length < 6) {
						terminate();
						return;
					} else {
						long ssnOfSubject = parseLong(param[1]);
						long timestamp = parseLong(param[2]);
						int division = Integer.parseInt(param[3]);
						long nurse = parseLong(param[4]);
						String notes = param[5];
						if (data.writeToRecord(loggedInUser, ssnOfSubject,
								timestamp, division, nurse, notes))
							sendToClient("recordnotes added");
						else
							sendToClient("no notes to record added");
					}
					break;
				}
			}

		} catch (IOException e) {
		}
	}

	private void sendToClient(String s) throws IOException {
		out.write(s + "\n\0");
		out.flush();
		UserInputLogger.log(String.format("TO %010d:", loggedInUser.getSsn())
				+ " \"" + s + "\"");
	}

	private void terminate() throws IOException {
		out.write(0);
		out.flush();
		out.close();
		in.close();
		UserInputLogger.log(String.format("ERROR: %010d:",
				loggedInUser.getSsn())
				+ " något som inte skulle hända hände");
		System.out.println("SLUTA!! skriv rätt nästa gång :)");
	}

	private static long parseLong(String s) {
		return Long.parseLong(s);
	}
}
